/**
 * Base64编码基础内容
 */
var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';


/**
 * 将字符串转换成Base64编码
 */
function btoa(s) {
   if (/([^\u0000-\u00ff])/.test(s)) {
      throw new Error('INVALID_CHARACTER_ERR');
   }
   var i = 0,
      prev,
      ascii,
      mod,
      result = [];
   while (i < s.length) {
      ascii = s.charCodeAt(i);
      mod = i % 3;
      switch (mod) {
         case 0:
            result.push(base64hash.charAt(ascii >> 2));
            break;
         case 1:
            result.push(base64hash.charAt((prev & 3) << 4 | (ascii >> 4)));
            break;
         case 2:
            result.push(base64hash.charAt((prev & 0x0f) << 2 | (ascii >> 6)));
            result.push(base64hash.charAt(ascii & 0x3f));
            break;
      }
      prev = ascii;
      i++;
   }
   if (mod == 0) {
      result.push(base64hash.charAt((prev & 3) << 4));
      result.push('==');
   } else if (mod == 1) {
      result.push(base64hash.charAt((prev & 0x0f) << 2));
      result.push('=');
   }

   return result.join('');
}


/**
 * 将Base64编码转换成字符串
 */
function atob(s) {
   s = s.replace(/\s|=/g, '');
   var cur,
      prev,
      mod,
      i = 0,
      result = [];

   while (i < s.length) {
      cur = base64hash.indexOf(s.charAt(i));
      mod = i % 4;
      switch (mod) {
         case 0:
            break;
         case 1:
            result.push(String.fromCharCode(prev << 2 | cur >> 4));
            break;
         case 2:
            result.push(String.fromCharCode((prev & 0x0f) << 4 | cur >> 2));
            break;
         case 3:
            result.push(String.fromCharCode((prev & 3) << 6 | cur));
            break;
      }
      prev = cur;
      i++;
   }
   return result.join('');
}


module.exports = {
   btoa: btoa,
   atob: atob
}